﻿using Microsoft.AspNetCore.Mvc;
using NetTaste;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Ongoal.Quotation.Cap;
using Ongoal.Quotation.Common;
using Ongoal.Quotation.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;

namespace Ongoal.Quotation.APIBase
{
    /// <summary>
    /// 单表操作
    /// </summary>

    [Route("Auto")]
    public class SingleTableController : WebAPIBase
    {
        private List<string> _baseModeProList = new List<string>();
        private List<string> _baseModeUpdateProList = new List<string>();
        private IMessagePublisher _messagePublisher;

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public SingleTableController(IMessagePublisher messagePublisher)
        {
            _baseModeProList = typeof(ModelBase).GetProperties().Select(t => t.Name).ToList();
            _baseModeUpdateProList = typeof(ModelBase).GetProperties().Where(t => t.Name != "ID").Select(t => t.Name).ToList();
            _messagePublisher = messagePublisher;
        }

        /// <summary>
        /// 获取单条数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="id">记录ID</param>
        /// <returns>单条数据</returns>
        /// <exception cref="ArgumentException"></exception>
        [HttpGet("{tableName}/{id?}")]
        public dynamic Get(string tableName, [FromRoute] int id = 0)
        {
            if (string.IsNullOrEmpty(tableName) || id <= 0)
            {
                throw new ArgumentException("表名及记录ID不可为空");
            }
            return this.Db!.GetDbContext(string.Empty).Queryable<dynamic>().AS(tableName).Where("ID=@ID", new { ID = id }).First();
        }

        /// <summary>
        /// 获取表的数据集合
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <returns>数据集合</returns>
        /// <exception cref="ArgumentException"></exception>
        [HttpGet("{tableName}")]
        public List<dynamic> GetAll(string tableName)
        {
            if (string.IsNullOrEmpty(tableName))
            {
                throw new ArgumentException("表名不可为空");
            }
            return this.Db!.GetDbContext(string.Empty).Queryable<dynamic>().AS(tableName).ToList();
        }

        /// <summary>
        /// 分页获取表的数据集合
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="size">分页大小(不可为空，如果小于0则默认为30)</param>
        /// <param name="index">页码(不可为空，如果小于0则默认为1)</param>
        /// <returns>数据集合</returns>
        /// <exception cref="ArgumentException"></exception>
        [HttpGet("{tableName}/{size?}/{index?}")]
        public SectionModel GetAll(string tableName, [FromRoute] int size, [FromRoute] int index)
        {
            if (string.IsNullOrEmpty(tableName))
            {
                throw new ArgumentException("表名不可为空");
            }
            SectionModel section = new SectionModel();
            if (size > 0)
            {
                section.Size = size;
            }
            if (index > 0)
            {
                section.Index = index;
            }
            int totalCount = 0;
            section.Items = this.Db!.GetDbContext(string.Empty).Queryable<dynamic>().AS(tableName).ToPageList(section.Index, section.Size, ref totalCount);
            section.Count = totalCount;

            return section;
        }

        /// <summary>
        /// 分页搜索数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="size">分页大小</param>
        /// <param name="index">页码</param>
        /// <param name="model">搜索实体</param>
        /// <returns></returns>
        [HttpPost("{tableName}/{size?}/{index?}")]
        public SectionModel Search(string tableName, int size, int index, [FromBody] SearchModel model)
        {
            if (string.IsNullOrEmpty(tableName))
            {
                throw new ArgumentException("表名不可为空");
            }
            if (model == null)
            {
                throw new ArgumentException("搜索参数不可为空");
            }
            SectionModel section = new SectionModel();
            if (size > 0)
            {
                section.Size = size;
            }
            if (index > 0)
            {
                section.Index = index;
            }
            string keySearch = string.Empty;
            var keyParametars = new Dictionary<string, object>();
            if (!string.IsNullOrEmpty(model.KeyWord))
            {
                keyParametars.Add("searchKey", $"%{model.KeyWord}%");
                if (model.KeyColList != null && model.KeyColList.Count > 0)
                {
                    StringBuilder builder = new StringBuilder();
                    foreach (var keyCol in model.KeyColList)
                    {
                        builder.Append($"OR {keyCol} like @searchKey ");
                    }
                    if (builder.Length > 0)
                    {
                        keySearch = builder.ToString().Substring(2);
                    }
                }
                else
                {
                    throw new ArgumentException("请指定关键字搜索列");
                }
            }
            StringBuilder condition = new StringBuilder();
            Dictionary<string, object> ConditionObj = new Dictionary<string, object>();
            if (model.Condition != null)
            {
                foreach (JProperty propertyInfo in model.Condition)
                {
                    condition.Append($"And {propertyInfo.Name}=@{propertyInfo.Name} ");
                    ConditionObj.Add(propertyInfo.Name, propertyInfo.Value);
                }
            }
            var conditionStr = condition.Length > 0 ? condition.ToString().Substring(3) : "";
            int totalCount = 0;
            section.Items = this.Db!.GetDbContext(string.Empty).Queryable<dynamic>().AS(tableName)
                .WhereIF(!string.IsNullOrEmpty(keySearch), keySearch, keyParametars)
                .WhereIF(condition.Length > 0, conditionStr, ConditionObj)
                .ToPageList(section.Index, section.Size, ref totalCount);
            section.Count = totalCount;

            return section;
        }

        /// <summary>
        /// 新增单条数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="obj">新增信息实体</param>
        /// <returns>新增对象的键值对</returns>
        /// <exception cref="ArgumentException"></exception>
        [HttpPost("{tableName}")]
        public dynamic Post(string tableName, [FromBody] InfoModel obj)
        {
            if (string.IsNullOrEmpty(tableName))
            {
                throw new ArgumentException("表名不可为空");
            }
            if (obj == null)
            {
                throw new ArgumentException("参数不可为空");
            }
            var insertObj = new Dictionary<string, object>();

            foreach (JProperty propertyInfo in obj.Data)
            {
                if (_baseModeProList.Contains(propertyInfo.Name) || propertyInfo.Name.StartsWith("_X_"))
                {
                    //忽略基础属性
                    continue;
                }
                if (insertObj.ContainsKey(propertyInfo.Name))
                {
                    insertObj[propertyInfo.Name] = propertyInfo.Value;
                }
                else
                {
                    insertObj.Add(propertyInfo.Name, propertyInfo.Value);
                }
            }
            try
            {
                if (obj.Check)
                {
                    //需要检查数据是否合法
                }
                if (obj.RepeatKeys != null && obj.RepeatKeys.Count > 0)
                {
                    //需要检查数据是否重复
                    StringBuilder stringBuilder = new StringBuilder();
                    var parametars = new Dictionary<string, object>();
                    foreach (var keyStr in obj.RepeatKeys)
                    {
                        if (insertObj.ContainsKey(keyStr))
                        {
                            stringBuilder.Append($"And {keyStr}=@{keyStr} ");
                            parametars.Add(keyStr, insertObj[keyStr]);
                        }
                    }
                    var whereStr = stringBuilder.ToString().Substring(3);

                    if (this.Db!.GetDbContext(string.Empty).Queryable<dynamic>().AS(tableName).Where(whereStr, parametars).Count() > 0)
                    {
                        throw new Exception("存在重复数据");
                    }
                }
                ////////////////////////////////////////////////////////////
                //////添加基础属性
                ///////////////////////////////////////////////////////////
                DateTime currentTime= DateTime.Now;
                insertObj.Add("CreatorID", this.CurrentUser!.UserID);
                insertObj.Add("ModifyID", this.CurrentUser.UserID);
                insertObj.Add("CreateTime", currentTime);
                insertObj.Add("ModifyTime", currentTime);
                //////////////////////////////////////////////////////////

                var client = this.Db!.GetDbContext(string.Empty);
                if (tableName.ToLower().Trim() == "t_codetable")
                {
                    bool result = _messagePublisher.ExecuteDBAndPublish(client.Ado, () =>
                    {
                        var id = client.Insertable(insertObj).AS(tableName).ExecuteReturnBigIdentity();
                        if (id == 0)
                        {
                            throw new Exception("保存数据失败!");
                        }
                        insertObj["ID"] = id;
                        obj.Data.ID = id;
                        obj.Data.CreatorID = obj.Data.ModifyID = this.CurrentUser!.UserID;
                        obj.Data.CreateTime = obj.Data.ModifyTime = currentTime;
                        _messagePublisher!.PublishWithDefaultCallback(SubscribeConstantBase.CodeTable, JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonConvert.SerializeObject(obj.Data)));
                        
                        return true;
                    });
                    if (!result)
                    {
                        throw new Exception("保存数据失败!");
                    }
                    else
                    {
                        return obj.Data;
                    }
                }
                else
                {
                    var result = client.Insertable(insertObj).AS(tableName).ExecuteReturnBigIdentity();
                    if (result > 0)
                    {
                        obj.Data.ID = result;
                        return obj.Data;
                    }
                }
                throw new Exception("保存数据失败!");

            }
            catch
            {
                throw;
            }
        }


        /// <summary>
        /// 修改单条数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="obj">修改信息实体</param>
        /// <returns>修改后的键值对</returns>
        /// <exception cref="ArgumentException"></exception>
        [HttpPut("{tableName}")]
        public dynamic PUT(string tableName, [FromBody] InfoModel obj)
        {
            if (string.IsNullOrEmpty(tableName))
            {
                throw new ArgumentException("表名不可为空");
            }
            if (obj == null)
            {
                throw new ArgumentException("参数不可为空");
            }
            var updateObj = new Dictionary<string, object>();
            foreach (JProperty propertyInfo in obj.Data)
            {
                if (_baseModeUpdateProList.Contains(propertyInfo.Name) || propertyInfo.Name.StartsWith("_X_"))//如果是Vxe自动增加的属性则忽略
                {
                    //忽略基础属性
                    continue;
                }
                if (updateObj.ContainsKey(propertyInfo.Name))
                {
                    updateObj[propertyInfo.Name] = propertyInfo.Value;
                }
                else
                {
                    updateObj.Add(propertyInfo.Name, propertyInfo.Value);
                }
            }
            if (!updateObj.ContainsKey("ID"))
            {
                throw new ArgumentException("参数中不存在主键");
            }
            ////////////////////////////////////////////////////////////
            //////添加基础属性
            ///////////////////////////////////////////////////////////
            DateTime currentTime = DateTime.Now;
            updateObj.Add("ModifyID", this.CurrentUser!.UserID);
            updateObj.Add("ModifyTime", currentTime);
            //////////////////////////////////////////////////////////
            try
            {
                if (obj.Check)
                {
                    //需要检查数据是否合法
                }
                var client = this.Db!.GetDbContext(string.Empty);
                if (obj.RepeatKeys != null && obj.RepeatKeys.Count > 0)
                {
                    //需要检查数据是否重复
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.Append("ID!=@ID ");
                    var parametars = new Dictionary<string, object>();
                    parametars.Add("ID", updateObj["ID"]);
                    foreach (var keyStr in obj.RepeatKeys)
                    {
                        if (updateObj.ContainsKey(keyStr))
                        {
                            stringBuilder.Append($"And {keyStr}=@{keyStr} ");
                            parametars.Add(keyStr, updateObj[keyStr]);
                        }
                    }
                    var whereStr = stringBuilder.ToString();

                    if (client.Queryable<dynamic>().AS(tableName).Where(whereStr, parametars).Count() > 0)
                    {
                        throw new Exception("存在重复数据");
                    }
                }

                if (tableName.ToLower().Trim() == "t_codetable")
                {
                    bool result = _messagePublisher.ExecuteDBAndPublish(client.Ado, () =>
                    {
                        var effectCount = client.Updateable(updateObj).AS(tableName).WhereColumns("ID").IgnoreColumns("CreatorID", "CreateTime").ExecuteCommand();
                        if (effectCount != 1)
                        {
                            return false;
                        }
                        obj.Data.ModifyID = this.CurrentUser!.UserID;
                        obj.Data.ModifyTime = currentTime;
                        _messagePublisher!.PublishWithDefaultCallback(SubscribeConstantBase.CodeTable, JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonConvert.SerializeObject(obj.Data)));
                        return true;
                    });
                    if (!result)
                    {
                        throw new Exception("保存数据失败!");
                    }
                    else
                    {
                        return obj.Data;
                    }
                }
                else
                {
                    var result = client.Updateable(updateObj).AS(tableName).WhereColumns("ID").IgnoreColumns("CreatorID", "CreateTime").ExecuteCommand();
                    if (result == 1)
                    {
                        return obj.Data;
                    }
                }

                throw new Exception("保存数据失败!");
            }
            catch (Exception ex)
            {
                throw;
            }
        }


        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="idlist">需要删除的记录ID列表</param>
        /// <returns>成功与否</returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="Exception"></exception>
        [HttpDelete("{tableName}")]
        public dynamic Delete(string tableName, [FromBody] List<int> idlist)
        {
            if (string.IsNullOrEmpty(tableName))
            {
                throw new ArgumentException("表名不可为空");
            }
            if (idlist == null || idlist.Count == 0)
            {
                throw new ArgumentException("参数不可为空");
            }
            var client = Db!.GetDbContext(string.Empty);
            try
            {
                if (tableName.ToLower().Trim() == "t_codetable")
                {
                    bool result = _messagePublisher.ExecuteDBAndPublish(client.Ado, () =>
                    {
                        if (client.Deleteable<dynamic>().AS(tableName).Where(" ID in (@id)", new { id = idlist.ToArray() }).ExecuteCommand() != idlist.Count)
                        {
                            return false;
                        }
                        _messagePublisher!.PublishWithDefaultCallback(SubscribeConstantBase.DeleteCodeTable, idlist);
                        return true;
                    });
                    return result;
                }
                else
                {
                    client.BeginTran();
                    try
                    {
                        if (client.Deleteable<dynamic>().AS(tableName).Where(" ID in (@id)", new { id = idlist.ToArray() }).ExecuteCommand() == idlist.Count)
                        {
                            client.CommitTran();
                            return true;
                        }
                        else
                        {
                            client.RollbackTran();
                            return false;
                        }
                    }
                    catch {
                        client.RollbackTran();
                        throw new Exception("删除过程中发生异常");
                    }
                }
            }
            catch
            {
                throw new Exception("删除过程中发生异常");
            }
        }


    }
}
